#include"../log.hpp"

// #include<stdlib.h>

const int queue_size=10;
Log_buffer_queue<int> queue(queue_size,true);
std::atomic<int> pro_count{0};
std::atomic<int> con_count{0};

void produer(int p_num)
{
    long long tid=tid_to_ll(std::this_thread::get_id());
    DBG_LOG("[tid:%lld] %d elements should be produced\n",tid,p_num);
    int i=0;
    while(i<p_num)
    {
        bool ret=queue.push(i);
        if(ret)
        {
            DBG_LOG("[tid:%lld]++++ produced no.%d element\n",tid,i+1);
            pro_count.fetch_add(1);
            i++;
        }
        else
        {
            DBG_LOG("[tid:%lld]**** push fail,queue is full\n",tid);
        }
    }
}

void consumer(int c_num)
{
    long long tid=tid_to_ll(std::this_thread::get_id());
    DBG_LOG("[tid:%lld] %d elements should be consumed\n",tid,c_num);
    int tmp;
    for(int i=0;i<c_num;i++)
    {
        queue.pop(tmp);
        DBG_LOG("[tid:%lld]---- consumed no.%d element\n",tid,i+1);
        con_count.fetch_add(1);
    }
}


void test_full_queue(Log_buffer_queue<int>& q,bool test=false)
{
    for(int i=0;i<q.get_capacity();i++)q.push(i);

    if(test)
    {
        int val;
        q.front(val);
        assert(val==0);

        for(int i=0;i<q.get_capacity();i++)
        {
            q.pop(val);
            DBG_LOG("pop log: %d\n",val);

            assert(val==i);
            if(i==q.get_capacity()-1)break;

            q.front(val);
            assert(val==i+1);
        }
    }
}

int main()
{
    set_level(DBG_LEVEL);

#if 1
    //阻塞队列接口测试
    assert(queue.is_empty());
    assert(queue.get_capacity()==queue_size);
    assert(queue.get_rcnt()==0);
    assert(queue.get_wcnt()==0);

    test_full_queue(queue);
    assert(queue.is_full());
    assert(queue.get_rcnt()==0);
    assert(queue.get_wcnt()==queue_size);

    queue.clear();
    assert(queue.is_empty());
    assert(queue.get_rcnt()==0);
    assert(queue.get_wcnt()==0);

    test_full_queue(queue,true);
    assert(queue.get_rcnt()==queue_size);
    assert(queue.get_wcnt()==queue_size);
    assert(queue.is_empty());
    test_full_queue(queue);
    assert(queue.get_rcnt()==queue_size);
    assert(queue.get_wcnt()==queue_size*2);

    queue.clear();
    int tmp;
    auto start=std::chrono::steady_clock::now();
    bool ret=queue.pop(tmp,2000);
    auto end=std::chrono::steady_clock::now();
    auto duration=std::chrono::duration_cast<std::chrono::milliseconds>(end-start);
    DBG_LOG("cond wait_for duration:%d ms\n",static_cast<int>(duration.count()));
    assert(!ret);
    DBG_LOG("buffer queue function test pass\n");
#else
    //多线程下生成消费模型测试
    queue.clear();
    test_full_queue(queue);
    int origin_num=queue.get_size();
    assert(origin_num==queue_size);
    DBG_LOG("------------------------------------------\n");
    DBG_LOG("buffer queue capacity is %d\n", queue_size);
    DBG_LOG("origin element num is %d\n", origin_num);
    DBG_LOG("------------------------------------------\n");

    int p_num1=100;
    int p_num2=50;
    int c_num1=160;
    std::thread p1(produer,p_num1);
    std::thread p2(produer,p_num2);
    std::thread c1(consumer,c_num1);
    p1.join();
    p2.join();
    c1.join();

    //load返回包含的值
    DBG_LOG("\n");
    DBG_LOG("origin element num is %d\n",origin_num);
    DBG_LOG("totally produced %d elements\n",pro_count.load());
    DBG_LOG("totally consumed %d elements\n",con_count.load());

    assert(queue.get_size()==(p_num1 + p_num2 + queue_size - c_num1));
    assert(queue.get_rcnt()==c_num1);
    assert(queue.get_wcnt()==(queue_size + p_num1 + p_num2));

    DBG_LOG("buffer queue mutithread test pass\n");
#endif
    return 0;
}